package internal

import (
	"GameServer/Common/utils"
	"GameServer/Game/dbmodule"
	"GameServer/Game/lib"
	"GameServer/Game/m"
	"fmt"
	"sort"
	"time"

	log "github.com/sirupsen/logrus"
)

// 每组人数控制
const EACH_GROUP = 50

// 委托排行
type EntrustRank struct {
	GroupIds []int64          //
	Robots   map[string]int64 // key：机器人uid，val：组id
	Activ    *m.ERActiv
}

func NewEntrustRank() *EntrustRank {
	return &EntrustRank{}
}

// 启动服务器，入口
func (this *EntrustRank) Init() {
	// 获取活动列表
	activ, err := lib.GetCurrentEntrustActiv()
	if err != nil {
		// 没有开始的委托活动
		log.WithFields(log.Fields{
			"err": err,
		}).Error("委托活动")
		return
	}
	// 加载数据库
	act := m.GetERActiv(1)
	// 1、数据库没有活动 2、数据库的活动tid和委托活动tid不一样
	if act.ActivId == 0 || act.ActivId != int64(activ.Id) {
		beginTime, _ := utils.LayoutToTime(activ.BeginTime)
		endTime, _ := utils.LayoutToTime(activ.EndTime)
		// 记录活动
		act.ActivId = int64(activ.Id)
		act.BeginTime = beginTime.Unix()
		act.EndTime = endTime.Unix()
		act.RankRewd = int64(activ.RankReward)
		act.Update(act)
		this.Activ = act
		// 开始分组
		this.DivGroup()
		return
	}
	// 数据库已经有活动了
	this.Activ = act

	// 数据库的活动tid和委托活动tid一样，把数据库的数据取出来
	// 加载团队
	lgroup := make([]*m.ERGroup, 0)
	err = dbmodule.MgoDB.GameDB.FindAll("ERGroup", nil, nil, &lgroup)
	if err != nil {
		log.WithFields(log.Fields{
			"err": err,
		}).Error("获取ERGroup失败")
		return
	}
	// 记录分组信息
	this.GroupIds = make([]int64, 0)
	this.Robots = make(map[string]int64)
	for _, item := range lgroup {
		this.GroupIds = append(this.GroupIds, item.Uid)
		for _, item1 := range item.LGamer {
			if item1.Robot { // 记录机器人
				this.Robots[item1.Uid.Hex()] = item1.GroupId
			}
		}
	}
}

func (this *EntrustRank) Run(closeSig chan bool) {
	for {
		select {
		case <-closeSig:
			return
		case <-time.After(time.Hour):
			this.RobotAddHonor()
		}
	}
}

func (this *EntrustRank) Destroy() {

}

// 分组
func (this *EntrustRank) DivGroup() {
	// 将同一章的50个玩家+至少10台机器人放进一个组
	allUser := make([]*m.User, 0)
	err := dbmodule.MgoDB.GameDB.FindAll("user", nil, nil, &allUser)
	if err != nil {
		log.WithFields(log.Fields{
			"method": "DivGroup",
			"err":    err,
		}).Error("委托，获取所有玩家失败")
		return
	}
	// 对所有玩家章节进行排序
	sort.Slice(allUser, func(i, j int) bool {
		return allUser[i].MaxPos.LockBlockTid > allUser[j].MaxPos.LockBlockTid
	})

	// 创建所有委托玩家
	allGamer := make([]*m.ERGamer, 0)
	for _, item := range allUser {
		gamer := &m.ERGamer{
			Uid:         item.Uid,
			AvatarFrame: item.AvatarFrame,
			Head:        item.Head,
			Name:        item.Name,
		}
		allGamer = append(allGamer, gamer)
	}
	// 玩家数量
	length := len(allUser)
	// 计算补充机器人的数量
	numRobot := EACH_GROUP - length%EACH_GROUP
	for i := 0; i < numRobot; i++ {
		allGamer = append(allGamer, m.NewERGamerRobot())
	}

	this.GroupIds = make([]int64, 0)
	this.Robots = make(map[string]int64)
	num := length/EACH_GROUP + 1 // 组数
	for i := 0; i < num; i++ {
		erg := &m.ERGroup{
			Uid:    int64(i),
			LGamer: make([]*m.ERGamer, 0),
			MGamer: make(map[string]int64),
		}
		groupId := int64(i)
		// 50人加入小组
		for j := i * EACH_GROUP; j < (i+1)*EACH_GROUP; j++ {
			gamer := allGamer[j]
			gamer.GroupId = groupId
			erg.LGamer = append(erg.LGamer, gamer)

			if gamer.Robot {
				this.Robots[gamer.Uid.Hex()] = groupId
			} else {
				gamer.Update(gamer)
			}
		}
		// 10个机器人加入小组
		for j := 0; j < 10; j++ {
			gamer := m.NewERGamerRobot()
			gamer.GroupId = groupId
			gamer.Robot = true
			erg.LGamer = append(erg.LGamer, gamer)

			this.Robots[gamer.Uid.Hex()] = groupId
		}

		erg.ReSort()

		this.GroupIds = append(this.GroupIds, int64(i))
		erg.Update(erg)
	}
}

// 检测活动
func (this *EntrustRank) CheckActiv() {
	// 获取当前委托任务
	activ, err := lib.GetCurrentEntrustActiv()
	if err != nil { // 没有委托任务
		this.DelActiv()
		return
	}
	beginTime, _ := utils.LayoutToTime(activ.BeginTime)
	endTime, _ := utils.LayoutToTime(activ.EndTime)

	// 当前时间
	nowTime := utils.TNow()
	// 当前时间大于委托活动结束时间，活动结束，或者无效活动。
	if endTime.Unix() < nowTime.Unix() {
		// 清除分组
		this.DelActiv()
		return
	}

	// 活动正在进行中
	// 当前时间小于活动时间，将活动记录
	activId := int64(activ.Id)

	// 该活动已经启动了。
	if this.Activ != nil && activId == this.Activ.ActivId {
		log.WithFields(log.Fields{
			"method": "CheckActiv",
		}).Error("已经有委托活动启动了")
		return
	}
	act := &m.ERActiv{
		Uid:       1,
		ActivId:   activId,
		BeginTime: beginTime.Unix(),
		EndTime:   endTime.Unix(),
		RankRewd:  int64(activ.RankReward),
	}
	act.Update(act)
	this.Activ = act

	// 委托分组
	this.DivGroup()
}

// 分发排名奖励
func (this *EntrustRank) DispatchRankReward(SendMailFunc func(uid string, title string, content string, resGoods []*m.Goods)) {
	if this.Activ == nil || this.Activ.ActivId == 0 || utils.TNow().Unix() < this.Activ.EndTime {
		log.WithFields(log.Fields{
			"method": "EntrustRank.DispatchReward",
		}).Error("委托活动不存在、活动未开始、活动未结束。")
		return
	}

	// 排名奖励表
	rewardList, err := lib.GetActRankRewardList(this.Activ.RankRewd)
	if err != nil {
		log.WithFields(log.Fields{
			"method":   "DispatchReward",
			"rewardId": this.Activ.RankRewd,
		}).Error("没有找到活动排名奖励")
		return
	}

	for _, item := range this.GroupIds {
		g := m.GetERGroup(item)
		g.ReSort() // 重新排序
		// 遍历玩家，发放奖励
		for _, gamer := range g.LGamer {
			if gamer.Robot || gamer.Honor == 0 { // 是机器人 荣誉为零 不发奖励
				continue
			}
			if reward, ok := rewardList[gamer.RankId+1]; ok {
				var mailTitle string = "Entrust ranking Award"
				var mailContent string = fmt.Sprintf("Your rank is: %d", gamer.RankId+1)
				resGoods := make([]*m.Goods, 0)
				if reward.Rewards != nil && len(reward.Rewards) > 0 {
					for _, item := range reward.Rewards {
						resGoods = append(resGoods, &m.Goods{
							Tid: int64(item.Key),
							Num: int64(item.Value),
						})
					}
				}
				SendMailFunc(gamer.Uid.Hex(), mailTitle, mailContent, resGoods)
			}
		}
	}
}

// 删除排名活动
func (this *EntrustRank) DelActiv() {
	activ := &m.ERActiv{Uid: 1}
	activ.Update(activ)
	this.Activ = activ
}

func (this *EntrustRank) RobotAddHonor() {
	if this.Activ == nil || this.Activ.ActivId == 0 {
		return
	}
	for key, val := range this.Robots {
		honor := utils.RandomEntr()
		group := m.GetERGroup(val)
		group.CalcHonor(key, honor)
	}
}
